package com.pj.ca.util;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.HmacAlgorithms;
import org.apache.commons.codec.digest.HmacUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 描述： hmac token算法 单向 简单实现
 *
 * @author pengjun
 * @date 2021/11/3 16:36
 */
public class SimpleTokenManager {
    private HmacUtils hmac;
    public SimpleTokenManager(String hmacKey) {
        this.hmac=new HmacUtils(HmacAlgorithms.HMAC_MD5, hmacKey);
    }
    public  String createToken(Map<String,String> data, Long time, TimeUnit timeUnit) {
        Long end=System.currentTimeMillis()+timeUnit.toMillis(time);
        data.put("end", String.valueOf(end));
        String signData=mapToString(data);
        String sign = Base64.encodeBase64URLSafeString(hmac.hmac(signData));
        String token=Base64.encodeBase64URLSafeString(signData.getBytes())+"."+sign;
        return token;
    }
    public  String createToken(String hmacKey,Map<String,String> data) {
        String signData=mapToString(data);
        String sign = Base64.encodeBase64URLSafeString(new HmacUtils(HmacAlgorithms.HMAC_MD5, hmacKey).hmac(signData));
        String token=Base64.encodeBase64URLSafeString(signData.getBytes())+"."+sign;
        return token;
    }

    public   Map<String,String>  vafy(String token) throws SecurityException  {
        if(null==token||"".equals(token)) {
            throw new SecurityException("token格式非法");
        }
        String[] split = token.split("\\.");
        if(split.length>2) {
            throw new SecurityException("token格式非法");
        }
        String sign=split[1];
        byte[] srcData=Base64.decodeBase64(split[0]);
        String data=new String(srcData);
        String sign2 = Base64.encodeBase64URLSafeString(hmac.hmac(srcData));
        if(!sign2.equals(sign)){
            throw new SecurityException("token签名非法");
        }
        Map<String, String> stringToMap = stringToMap(data);
        if(!stringToMap.containsKey("end")){
            return stringToMap;
        }
        Long end=Long.parseLong(stringToMap.get("end"));
        if(System.currentTimeMillis()>end){
            throw new SecurityException("token过期");
        }
        return stringToMap;

    }
    private Map<String,String> stringToMap(String mapString){
        String[] split = mapString.split(";");
        Map<String,String> map=new HashMap<String, String>(split.length);
        for(String keyValue:split){
            String[] kv = keyValue.split("=");
            map.put(kv[0], kv[1]);
        }
        return map;
    }
    private String mapToString(Map<String,String> map){
        StringBuilder buf=new StringBuilder();
        map.forEach((key,value)->{
            buf.append(key).append("=").append(map.get(key)).append(";");
        });
        return buf.substring(0, buf.length()-1);

    }

}
